/*
* V.java
* Copyright (C) 2003
* 
* $Id: V.java,v 1.5 2005/07/01 14:20:50 hzi Exp $
*/
/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
using System;
using Globals = Suake2.UI.Globals;
using Cmd = Suake2.UI.game.Cmd;
using cvar_t = Suake2.UI.game.cvar_t;
using Suake2.UI.qcommon;
using Timer = Suake2.UI.sys.Timer;
using Math3D = Suake2.UI.util.Math3D;
using Vargs = Suake2.UI.util.Vargs;
//UPGRADE_TODO: The type 'java.nio.FloatBuffer' could not be found. If it was not included in the conversion, there may be compiler issues. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1262'"
using FloatBuffer = java.nio.FloatBuffer;
namespace Suake2.UI.client
{
	
	/// <summary> V</summary>
	public sealed class V:Globals
	{
		public class AnonymousClassxcommand_t:xcommand_t
		{
			public override void  execute()
			{
				jake2.Globals.gun_frame++;
				Com.Printf("frame " + jake2.Globals.gun_frame + "\n");
			}
		}
		public class AnonymousClassxcommand_t1:xcommand_t
		{
			public override void  execute()
			{
				jake2.Globals.gun_frame--;
				if (jake2.Globals.gun_frame < 0)
					jake2.Globals.gun_frame = 0;
				Com.Printf("frame " + jake2.Globals.gun_frame + "\n");
			}
		}
		public class AnonymousClassxcommand_t2:xcommand_t
		{
			public override void  execute()
			{
				if (Cmd.Argc() != 2)
				{
					jake2.Globals.gun_model = null;
					return ;
				}
				System.String name = "models/" + Cmd.Argv(1) + "/tris.md2";
				jake2.Globals.gun_model = Suake2.UI.Globals.re.RegisterModel(name);
			}
		}
		public class AnonymousClassxcommand_t3:xcommand_t
		{
			public override void  execute()
			{
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				Com.Printf("(%i %i %i) : %i\n", new Vargs(4).add((int) jake2.Globals.cl.refdef.vieworg[0]).add((int) jake2.Globals.cl.refdef.vieworg[1]).add((int) jake2.Globals.cl.refdef.vieworg[2]).add((int) jake2.Globals.cl.refdef.viewangles[jake2.Defines.YAW]));
			}
		}
		
		internal static cvar_t cl_testblend;
		
		internal static cvar_t cl_testparticles;
		
		internal static cvar_t cl_testentities;
		
		internal static cvar_t cl_testlights;
		
		internal static cvar_t cl_stats;
		
		internal static int r_numdlights;
		
		internal static dlight_t[] r_dlights = new dlight_t[MAX_DLIGHTS];
		
		internal static int r_numentities;
		
		internal static entity_t[] r_entities = new entity_t[MAX_ENTITIES];
		
		internal static int r_numparticles;
		
		//static particle_t[] r_particles = new particle_t[MAX_PARTICLES];
		
		internal static lightstyle_t[] r_lightstyles = new lightstyle_t[MAX_LIGHTSTYLES];
		
		/*
		* ==================== V_ClearScene
		* 
		* Specifies the model that will be used as the world ====================
		*/
		internal static void  ClearScene()
		{
			r_numdlights = 0;
			r_numentities = 0;
			r_numparticles = 0;
		}
		
		/*
		* ===================== V_AddEntity
		* 
		* =====================
		*/
		internal static void  AddEntity(entity_t ent)
		{
			if (r_numentities >= MAX_ENTITIES)
				return ;
			r_entities[r_numentities++].set_Renamed(ent);
		}
		
		/*
		* ===================== V_AddParticle
		* 
		* =====================
		*/
		internal static void  AddParticle(float[] org, int color, float alpha)
		{
			if (r_numparticles >= MAX_PARTICLES)
				return ;
			
			int i = r_numparticles++;
			
			int c = particle_t.colorTable[color];
			//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
			c |= (int) (alpha * 255) << 24;
			particle_t.colorArray.put(i, c);
			
			i *= 3;
			FloatBuffer vertexBuf = particle_t.vertexArray;
			vertexBuf.put(i++, org[0]);
			vertexBuf.put(i++, org[1]);
			vertexBuf.put(i++, org[2]);
		}
		
		/*
		* ===================== V_AddLight
		* 
		* =====================
		*/
		internal static void  AddLight(float[] org, float intensity, float r, float g, float b)
		{
			dlight_t dl;
			
			if (r_numdlights >= MAX_DLIGHTS)
				return ;
			dl = r_dlights[r_numdlights++];
			Math3D.VectorCopy(org, dl.origin);
			dl.intensity = intensity;
			dl.color[0] = r;
			dl.color[1] = g;
			dl.color[2] = b;
		}
		
		/*
		* ===================== V_AddLightStyle
		* 
		* =====================
		*/
		internal static void  AddLightStyle(int style, float r, float g, float b)
		{
			lightstyle_t ls;
			
			if (style < 0 || style > MAX_LIGHTSTYLES)
				Com.Error(ERR_DROP, "Bad light style " + style);
			ls = r_lightstyles[style];
			
			ls.white = r + g + b;
			ls.rgb[0] = r;
			ls.rgb[1] = g;
			ls.rgb[2] = b;
		}
		
		// stack variable
		//UPGRADE_NOTE: Final was removed from the declaration of 'origin'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
		private static readonly float[] origin = new float[]{0, 0, 0};
		/*
		* ================ V_TestParticles
		* 
		* If cl_testparticles is set, create 4096 particles in the view
		* ================
		*/
		internal static void  TestParticles()
		{
			int i, j;
			float d, r, u;
			
			r_numparticles = 0;
			for (i = 0; i < MAX_PARTICLES; i++)
			{
				d = i * 0.25f;
				r = 4 * ((i & 7) - 3.5f);
				u = 4 * (((i >> 3) & 7) - 3.5f);
				
				for (j = 0; j < 3; j++)
					origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j] * d + cl.v_right[j] * r + cl.v_up[j] * u;
				
				AddParticle(origin, 8, cl_testparticles.value_Renamed);
			}
		}
		
		/*
		* ================ V_TestEntities
		* 
		* If cl_testentities is set, create 32 player models ================
		*/
		internal static void  TestEntities()
		{
			int i, j;
			float f, r;
			entity_t ent;
			
			r_numentities = 32;
			//memset (r_entities, 0, sizeof(r_entities));
			for (i = 0; i < r_entities.Length; i++)
				r_entities[i].clear();
			
			for (i = 0; i < r_numentities; i++)
			{
				ent = r_entities[i];
				
				r = 64 * ((i % 4) - 1.5f);
				f = 64 * (i / 4) + 128;
				
				for (j = 0; j < 3; j++)
					ent.origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j] * f + cl.v_right[j] * r;
				
				ent.model = cl.baseclientinfo.model;
				ent.skin = cl.baseclientinfo.skin;
			}
		}
		
		/*
		* ================ V_TestLights
		* 
		* If cl_testlights is set, create 32 lights models ================
		*/
		internal static void  TestLights()
		{
			int i, j;
			float f, r;
			dlight_t dl;
			
			r_numdlights = 32;
			//memset (r_dlights, 0, sizeof(r_dlights));
			for (i = 0; i < r_dlights.Length; i++)
				r_dlights[i] = new dlight_t();
			
			for (i = 0; i < r_numdlights; i++)
			{
				dl = r_dlights[i];
				
				r = 64 * ((i % 4) - 1.5f);
				f = 64 * (i / 4) + 128;
				
				for (j = 0; j < 3; j++)
					dl.origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j] * f + cl.v_right[j] * r;
				dl.color[0] = ((i % 6) + 1) & 1;
				dl.color[1] = (((i % 6) + 1) & 2) >> 1;
				dl.color[2] = (((i % 6) + 1) & 4) >> 2;
				dl.intensity = 200;
			}
		}
		
		//UPGRADE_NOTE: The initialization of  'Gun_Next_f' was moved to static method 'jake2.client.V'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static xcommand_t Gun_Next_f;
		
		//UPGRADE_NOTE: The initialization of  'Gun_Prev_f' was moved to static method 'jake2.client.V'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static xcommand_t Gun_Prev_f;
		
		//UPGRADE_NOTE: The initialization of  'Gun_Model_f' was moved to static method 'jake2.client.V'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static xcommand_t Gun_Model_f;
		
		/*
		* ================== V_RenderView
		* 
		* ==================
		*/
		internal static void  RenderView(float stereo_separation)
		{
			//		extern int entitycmpfnc( const entity_t *, const entity_t * );
			//
			if (cls.state != ca_active)
				return ;
			
			if (!cl.refresh_prepped)
				return ; // still loading
			
			if (cl_timedemo.value_Renamed != 0.0f)
			{
				if (cl.timedemo_start == 0)
					cl.timedemo_start = Timer.Milliseconds();
				cl.timedemo_frames++;
			}
			
			// an invalid frame will just use the exact previous refdef
			// we can't use the old frame if the video mode has changed, though...
			if (cl.frame.valid && (cl.force_refdef || cl_paused.value_Renamed == 0.0f))
			{
				cl.force_refdef = false;
				
				V.ClearScene();
				
				// build a refresh entity list and calc cl.sim*
				// this also calls CL_CalcViewValues which loads
				// v_forward, etc.
				CL_ents.AddEntities();
				
				if (cl_testparticles.value_Renamed != 0.0f)
					TestParticles();
				if (cl_testentities.value_Renamed != 0.0f)
					TestEntities();
				if (cl_testlights.value_Renamed != 0.0f)
					TestLights();
				if (cl_testblend.value_Renamed != 0.0f)
				{
					cl.refdef.blend[0] = 1.0f;
					cl.refdef.blend[1] = 0.5f;
					cl.refdef.blend[2] = 0.25f;
					cl.refdef.blend[3] = 0.5f;
				}
				
				// offset vieworg appropriately if we're doing stereo separation
				if (stereo_separation != 0)
				{
					float[] tmp = new float[3];
					
					Math3D.VectorScale(cl.v_right, stereo_separation, tmp);
					Math3D.VectorAdd(cl.refdef.vieworg, tmp, cl.refdef.vieworg);
				}
				
				// never let it sit exactly on a node line, because a water plane
				// can
				// dissapear when viewed with the eye exactly on it.
				// the server protocol only specifies to 1/8 pixel, so add 1/16 in
				// each axis
				cl.refdef.vieworg[0] = (float) (cl.refdef.vieworg[0] + 1.0 / 16);
				cl.refdef.vieworg[1] = (float) (cl.refdef.vieworg[1] + 1.0 / 16);
				cl.refdef.vieworg[2] = (float) (cl.refdef.vieworg[2] + 1.0 / 16);
				
				cl.refdef.x = scr_vrect.x;
				cl.refdef.y = scr_vrect.y;
				cl.refdef.width = scr_vrect.width;
				cl.refdef.height = scr_vrect.height;
				cl.refdef.fov_y = Math3D.CalcFov(cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
				cl.refdef.time = cl.time * 0.001f;
				
				cl.refdef.areabits = cl.frame.areabits;
				
				if (cl_add_entities.value_Renamed == 0.0f)
					r_numentities = 0;
				if (cl_add_particles.value_Renamed == 0.0f)
					r_numparticles = 0;
				if (cl_add_lights.value_Renamed == 0.0f)
					r_numdlights = 0;
				if (cl_add_blend.value_Renamed == 0)
				{
					Math3D.VectorClear(cl.refdef.blend);
				}
				
				cl.refdef.num_entities = r_numentities;
				cl.refdef.entities = r_entities;
				cl.refdef.num_particles = r_numparticles;
				cl.refdef.num_dlights = r_numdlights;
				cl.refdef.dlights = r_dlights;
				cl.refdef.lightstyles = r_lightstyles;
				
				cl.refdef.rdflags = cl.frame.playerstate.rdflags;
				
				// sort entities for better cache locality
				// !!! useless in Java !!!
				//Arrays.sort(cl.refdef.entities, entitycmpfnc);
			}
			
			re.RenderFrame(cl.refdef);
			if (cl_stats.value_Renamed != 0.0f)
				Com.Printf("ent:%i  lt:%i  part:%i\n", new Vargs(3).add(r_numentities).add(r_numdlights).add(r_numparticles));
			if (log_stats.value_Renamed != 0.0f && (log_stats_file != null))
				try
				{
					log_stats_file.Write(r_numentities + "," + r_numdlights + "," + r_numparticles);
				}
				catch (System.IO.IOException e)
				{
				}
			
			SCR.AddDirtyPoint(scr_vrect.x, scr_vrect.y);
			SCR.AddDirtyPoint(scr_vrect.x + scr_vrect.width - 1, scr_vrect.y + scr_vrect.height - 1);
			
			SCR.DrawCrosshair();
		}
		
		/*
		* ============= V_Viewpos_f =============
		*/
		//UPGRADE_NOTE: The initialization of  'Viewpos_f' was moved to static method 'jake2.client.V'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
		internal static xcommand_t Viewpos_f;
		
		public static void  Init()
		{
			Cmd.AddCommand("gun_next", Gun_Next_f);
			Cmd.AddCommand("gun_prev", Gun_Prev_f);
			Cmd.AddCommand("gun_model", Gun_Model_f);
			
			Cmd.AddCommand("viewpos", Viewpos_f);
			
			crosshair = Cvar.Get("crosshair", "0", CVAR_ARCHIVE);
			
			cl_testblend = Cvar.Get("cl_testblend", "0", 0);
			cl_testparticles = Cvar.Get("cl_testparticles", "0", 0);
			cl_testentities = Cvar.Get("cl_testentities", "0", 0);
			cl_testlights = Cvar.Get("cl_testlights", "0", 0);
			
			cl_stats = Cvar.Get("cl_stats", "0", 0);
		}
		static V()
		{
			{
				for (int i = 0; i < r_dlights.Length; i++)
					r_dlights[i] = new dlight_t();
				for (int i = 0; i < r_entities.Length; i++)
					r_entities[i] = new entity_t();
				for (int i = 0; i < r_lightstyles.Length; i++)
					r_lightstyles[i] = new lightstyle_t();
			}
			Gun_Next_f = new AnonymousClassxcommand_t();
			Gun_Prev_f = new AnonymousClassxcommand_t1();
			Gun_Model_f = new AnonymousClassxcommand_t2();
			Viewpos_f = new AnonymousClassxcommand_t3();
		}
	}
}